<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>TinyOS 2.x Boot Sequence</title>
<meta name="author" content="Philip Levis" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009-02-03 23:07:32 $
:version: $Revision: 1.15 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="tinyos-2-x-boot-sequence">
<h1 class="title">TinyOS 2.x Boot Sequence</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">107</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Philip Levis</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>This memo documents the structure and implementation of the mote
boot sequence in TinyOS 2.x.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>TinyOS has a set of calling conventions and semantics in its boot
sequence. Earlier versions of TinyOS used an interface named
&quot;StdControl&quot; to take care of system initialization and starting
required software systems. Experience with several hardware platforms
showed StdControl to be insufficient, as it provided only a
synchronous interface. Additionally, StdControl bundled the notion of
initialization, which happens only at boot, with power management and
service control. TinyOS 2.x solves these problems by separating what
was once StdControl into three separate interfaces: one for
initialization, one for starting and stopping components, and one for
notification that the mote has booted. This memo describes the TinyOS
boot sequence and reasons for its semantics.</p>
</div>
<div class="section">
<h1><a id="tinyos-1-x-boot-sequence" name="tinyos-1-x-boot-sequence">2. TinyOS 1.x Boot Sequence</a></h1>
<p>The TinyOS 1.x boot sequence is uniform across most mote platforms
(TOSSIM has a very different boot sequence, as it is a PC
program). The module RealMain implements main(), and has the following
signature:</p>
<pre class="literal-block">
module RealMain {
  uses {
    command result_t hardwareInit();
    interface StdControl;
    interface Pot;
  }
}
</pre>
<p>The mote main() function uses a mix of nesC and C:</p>
<pre class="literal-block">
int main() __attribute__ ((C, spontaneous)) {
  call hardwareInit();
  call Pot.init(10);
  TOSH_sched_init();

  call StdControl.init();
  call StdControl.start();
  __nesc_enable_interrupt();

  while(1) {
    TOSH_run_task();
  }
}
</pre>
<p>Several problems exist. Some of these calls are artifacts of old
platforms: the Pot component refers to the mica variable potentiometer
for controlling radio transmission power, and for other platforms is a
stub component Some of the calls -- TOSH_sched_init and TOSH_run_task
-- are C functions that are implemented in other, automatically
included files. Separation from the nesC component model makes
changing what lies behind these functions more difficult than normal
in TinyOS.</p>
<p>More importantly, the initialization sequence has several
limitations. The component HPLInit implements the hardwareInit command
(wired by the component Main): hardware initialization may not be part
of a pure HPL layer. The scheduler is initialized after hardware,
which means that no hardware initialization can post a task if it
needs one. The StdControl interface combines component initialization
(init()) and activation (start()/stop()); if a component needs to be
initialized by RealMain, it must also be started. Separating these two
leads to more flexible power management, and distinguishes required
low-level components that must always be running (such as a Timer)
from high level components that can be power managed (such as an
application). Finally, some components that need to often need to be
started by main, such as a radio, do not follow a synchronous
start/stop model. In this case, some components can't operate properly
until the radio starts, but main has no mechanism for waiting for the
radio start completion event.</p>
</div>
<div class="section">
<h1><a id="tinyos-2-x-boot-interfaces" name="tinyos-2-x-boot-interfaces">3. TinyOS 2.x Boot Interfaces</a></h1>
<p>The TinyOS 2.x boot sequence uses three interfaces:</p>
<blockquote>
<ul class="simple">
<li>Init, for initializing component/hardware state</li>
<li>Scheduler, for initializing and running tasks</li>
<li>Boot, for signalling that the system has successfully booted</li>
</ul>
</blockquote>
<p>The Init interface has a single command, init():</p>
<pre class="literal-block">
interface Init {
  command error_t init();
}
</pre>
<p>Init provides a synchronous interface, enabling initialization
ordering. Unlike normal execution, in which operations from a wide
range of components need to be interleaved effectively, initialization
is a sequential, synchronous operation: no component can be started
until initialization is complete. If a particular component's
initialization requires waiting for interrupts or other asynchronous
events, then it must explicitly wait for them (e.g.,
with a spin loop), MUST NOT return until complete. Otherwise the system
may start before initialization is complete.</p>
<p>The Scheduler interface is for initializing and controlling task
execution. It is detailed in TEP 106 <a class="footnote-reference" href="#id7" id="id1" name="id1">[1]</a>.</p>
<p>The Boot interface has a single event, booted(), which the boot
sequence signals when it has completed:</p>
<pre class="literal-block">
interface Boot {
  event void booted();
}
</pre>
</div>
<div class="section">
<h1><a id="id2" name="id2">4. TinyOS 2.x Boot Sequence</a></h1>
<p>The module RealMainP implements the standard TinyOS 2.x boot sequence.
The configuration MainC wires some of RealMainP's interfaces to
components that implement standard abstractions and exports the others
that are application specific. Code above the Hardware Independent
Layer (TEP 2) SHOULD wire to MainC and not RealMainP:</p>
<pre class="literal-block">
module RealMainP {
  provides interface Booted;
  uses {
    interface Scheduler;
    interface Init as PlatformInit;
    interface Init as SoftwareInit;
  }
}
implementation {
  int main() __attribute__ ((C, spontaneous)) {
    atomic {
      platform_bootstrap();
      call Scheduler.init();
      call PlatformInit.init();
      while (call Scheduler.runNextTask());
      call SoftwareInit.init();
      while (call Scheduler.runNextTask());
    }
    __nesc_enable_interrupt();
    signal Boot.booted();
    call Scheduler.taskLoop();
    return -1;
  }
  default command error_t PlatformInit.init() { return SUCCESS; }
  default command error_t SoftwareInit.init() { return SUCCESS; }
  default event void Boot.booted() { }
}
</pre>
<div class="section">
<h2><a id="initialization" name="initialization">4.1 Initialization</a></h2>
<p>The first step in the boot sequence is initializing the system:</p>
<pre class="literal-block">
atomic {
  platform_bootstrap();
  call Scheduler.init();
  call PlatformInit.init();
  while (call Scheduler.runNextTask());
  call SoftwareInit.init();
  while (call Scheduler.runNextTask());
}
</pre>
<p>The first call, platform_bootstrap(), is a minimalist function that
places the system into an executable state. This function MUST NOT include
operations besides those which are absolutely necessary for further code,
such as scheduler initialization, to execute.
Examples of platform_bootstrap() operations are configuring the memory
system and setting the processor mode. Generally, platform_bootstrap()
is an empty function. TinyOS's top-level include file, <tt class="docutils literal"><span class="pre">tos.h</span></tt>, includes
a default implementation of this function which does nothing. If a platform
needs to replace the default, it SHOULD put it in a platform's
<tt class="docutils literal"><span class="pre">platform.h</span></tt> file as a #define. The implementation of <tt class="docutils literal"><span class="pre">tos.h</span></tt>
supports this:</p>
<pre class="literal-block">
/* This platform_bootstrap macro exists in accordance with TEP
   107. A platform may override this through a platform.h file. */
#include &lt;platform.h&gt;
#ifndef platform_bootstrap
#define platform_bootstrap() {}
#endif
</pre>
<p>The boot sequence has three separate initializations: Scheduler,
PlatformInit, and SoftwareInit. The boot configuration (MainC) wires
the first two automatically, to TinySchedulerC (discussed in TEP 106)
and to PlatformC:</p>
<pre class="literal-block">
configuration MainC {
  provides interface Boot;
  uses interface Init as SoftwareInit;
}
implementation {
  components PlatformC, RealMainP, TinySchedulerC;

  RealMainP.Scheduler -&gt; TinySchedulerC;
  RealMainP.PlatformInit -&gt; PlatformC;

  // Export the SoftwareInit and Booted for applications
  SoftwareInit = RealMainP.SoftwareInit;
  Boot = RealMainP;
}
</pre>
<p>MainC exports the Boot and SoftwareInit interfaces for applications to
wire to. TinySchedulerC is the standard name for the TinyOS
scheduler. As the initialization sequence requires being able to run
tasks, the boot sequence initializes it first. The second step of
initialization is to call PlatformInit.init(), which MainC wires to a
component named PlatformC. PlatformInit is for initializations which
must follow a very specific order due to hidden dependencies, e.g., as
part of making the overall hardware platform operable. One example of
this sort of initialization is clock calibration. Because PlatformInit
calls the component PlatformC, each platform can specify the required
initialization order. As these hidden dependencies must be due to
hardware, the sequence is platform-specific. A port of TinyOS to a
new plaform MUST include a component PlatformC which provides
one and only one instance of the Init interface.</p>
<p>Initializations invoked
through PlatformC meet some or all of the following criteria:</p>
<ol class="arabic simple">
<li>The initialization requires configuring hardware resources. This implies that the code is platform-specific.</li>
<li>The initialization should always be performed.</li>
<li>The initialization is a prerequisite for common services in the system.</li>
</ol>
<p>Three example operations that often belong in PlatformInit are I/O pin
configuration, clock calibration, and LED configuration. I/O pin
configuration meets the first two criteria. It should always be performed
(regardless of what components the OS uses) for low-power reasons:
incorrectly configured pins can draw current and prevent the MCU from
entering its lowest power sleep state <a class="footnote-reference" href="#id8" id="id3" name="id3">[2]</a>. Clock calibration meets
all three criteria. LED configuration is a special case: while it
nominally meets all three criteria, the most important one is the third:
as LEDs are often needed during SoftwareInit initialization, they must
be set up before it is invoked.</p>
<p>Note that not all code which meets some of these criteria is wired through
PlatformC. In particular, criterion 1 is typically necessary but not
sufficient to require PlatformC. For example, a timer system that
configures overflow and capture settings or  a UART stack that sets the
baud rate and transmission options can often be wired to SoftwareInit.
They are encapsulated abstractions which will not be invoked or
started until the boot event, and only need to be configured if the
system includes their functionality.</p>
<p>Components whose initialization does not directly depend on hardware
resources SHOULD wire to MainC.SoftwareInit. If a component requires a
specific initialization ordering, then it is responsible for
establishing that ordering. Due to the semantics of Init, this is
usually quite rare; a component SHOULD NOT introduce initialization
dependencies unless they are required.</p>
<p>One common approach is for a configuration to &quot;auto-wire&quot; the
initialization routines of its internal components. The configuration
does not provide an Init interface. Virtualized services
often take this approach, as the service, rather than the clients, is
what needs to be initialized. For example, the standard Timer
virtualization <a class="footnote-reference" href="#id9" id="id4" name="id4">[3]</a>, TimerMilliC, wires to TimerMilliP, which is
a very simple configuration that takes the underlying implementation
(HilTimerMilliC) and wires it to MainC:</p>
<pre class="literal-block">
configuration TimerMilliP {
  provides interface Timer&lt;TMilli&gt; as Timinitialization in ordererMilli[uint8_t id];
}
implementation {
  components HilTimerMilliC, MainC;
  MainC.SoftwareInit -&gt; HilTimerMilliC;
  TimerMilli = HilTimerMilliC;
}
</pre>
<p>Rather than require an application to wire HilTimerMilliC to MainC,
TimerMilliP does it automatically. When a component instantiates a
TimerMilliC, that names TimerMilliP, which will automatically make
sure that the timer system is initialized when TinyOS boots.</p>
</div>
<div class="section">
<h2><a id="interrupts-in-initialization" name="interrupts-in-initialization">4.2 Interrupts in Initialization</a></h2>
<p>Interrupts are not enabled until all calls to Init.init have returned.
If a component's initialization needs to handle interrupts, it can
do one of three things:</p>
<blockquote>
<ol class="arabic simple">
<li>If a status flag for the interrupt exists, the Init.init()
implementations SHOULD use a spin loop to test for when
an interrupt has been issued.</li>
<li>If no such flag exists, the Init.init() implementation MAY
temporarily enable interrupts, if doing so will not cause any other
components to handle an interrupt. That is, if a component enables
an interrupt, it MUST NOT enable interrupts whose handlers would
invoke any other component. Furthermore, when Init.init() exits,
the interrupts must be disabled.</li>
<li>If no such flag exists and there is no way to isolate which
interrupt handlers are called, then the component MUST rely
on mechanisms outside the Init sequence, such as SplitControl.</li>
</ol>
</blockquote>
<p>The boot sequence assumes that 1) is by far the dominant case. There
are, however, possible situations where a component might need to
handle an interrupt because of, e.g., hardware limitations (no pending
flag) or to catch a brief edge transition. In these cases, a component
can handle an interrupt in the boot sequence only if doing so will not
cause any other component to handle an interrupt. As they have all
been written assuming that interrupts are not enabled until after Init
completes, making one of them handle an interrupt could cause it to
fail.</p>
<p>Depending on what capabilities the hardware provides, there are
several ways to meet these requirements. The simplest is to push these
initialization edge cases out of the main boot sequence, e.g., into
SplitControl. A second possibility is to redirect the interrupt table,
if the MCU supports doing so. Whichever mechanism is chosen, extreme
care needs to be used in order to not disrupt the operation of other
components.</p>
<p>Unless part of a hardware abstraction architecture (HAA) <a class="footnote-reference" href="#id10" id="id5" name="id5">[4]</a>, the
Init.init() command MUST NOT assume that other components have been
initialized unless it has initialized them, and MUST NOT call any
functional interfaces on any components that might be shared or
interact with shared resources.  Components MAY call functions
on other components that are completely internal to the subsystem.
For example, a networking layer can  call queue operations to
initialize its queue, but a link layer must not send commands
over an SPI bus.  An HAA
component MAY make other calls to initialize hardware state. A
component that is not part of an HAA SHOULD NOT call Init.init() on
other components unless it needs to enforce a temporal ordering on
initialization.</p>
<p>If a component A depends on another component, B,
which needs to be initialized, then A SHOULD wire B's Init directly
to the boot sequence, unless there is a temporal ordering requirement to
the initialization. The purpose of this convention is to simplify
component initialization and the initialization sequence.</p>
</div>
</div>
<div class="section">
<h1><a id="implementation" name="implementation">5. Implementation</a></h1>
<p>The following files in <tt class="docutils literal"><span class="pre">tinyos-2.x/tos/system</span></tt> contain the reference
implementations of the TinyOS boot sequence:</p>
<blockquote>
<ul class="simple">
<li><tt class="docutils literal"><span class="pre">RealMainP.nc</span></tt> is the module containing the function <tt class="docutils literal"><span class="pre">main</span></tt>.</li>
<li><tt class="docutils literal"><span class="pre">MainC.nc</span></tt> is the configuration that wires RealMainP to
PlatformC and TinySchedulerC <a class="footnote-reference" href="#id7" id="id6" name="id6">[1]</a>.</li>
</ul>
</blockquote>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
<div class="line-block">
<div class="line">Philip Levis</div>
<div class="line">467 Soda Hall</div>
<div class="line">UC Berkeley</div>
<div class="line">Berkeley, CA 94720</div>
<div class="line"><br /></div>
<div class="line">phone - +1 510 290 5283</div>
<div class="line"><br /></div>
<div class="line">email - <a class="reference" href="mailto:pal&#64;cs.berkeley.edu">pal&#64;cs.berkeley.edu</a></div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">7. Citations</a></h1>
<table class="docutils footnote" frame="void" id="id7" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a name="id7">[1]</a></td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id6">2</a>)</em> TEP 106: Schedulers and Tasks.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id8" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id3" name="id8">[2]</a></td><td>TEP 112: Microcontroller Power Management.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id9" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id4" name="id9">[3]</a></td><td>TEP 102: Timers.</td></tr>
</tbody>
</table>
<table class="docutils footnote" frame="void" id="id10" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id5" name="id10">[4]</a></td><td>TEP 2: Hardware Abstraction Architecture.</td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
